﻿using Biomedica.Graphics;
using Biomedica.Screen.Mappers;
using DTWGestureRecognition;
using KinectLibrary;
using KinectWindows.Math;
using KinectWindows.Messages;
using KinectWindows.Nui.Nui.Detectors;
using KinectWindows.Nui.Nui.Postures;
using KinectWindows.Windows;
using NuiDicomPlayer.Nui.Gestures;
using NuiDicomPlayer.Nui.NavigationEngine;
using NuiDicomPlayer.Nui.Nui;
using NuiDicomPlayer.Nui.Speech;
using SkeletonRecorder.Kinect;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KinectWindows
{
    public static class WindowManager
    {

        public class WindowManagerLooper
        {
            public static Screen Scr;
          
            
            public static KinectHandGrabber GrabHand;
           
            public static SpeechGraber GrabSpeech;
            
            private static Boolean Run { set; get; }
            public static void Start()
            {
                Scr= new Screen();
              
              
                Scr.InitScreen();
           
               
                GrabHand = new KinectHandGrabber(Scr);
                GrabHand.StartSensor();
            
                GrabSpeech = new SpeechGraber();
                Run = true;
                while (Run)
                {
                    NuiEvent nevent = NuiEventManager.GetEvent();
                    if (nevent != null)
                    {
                       // ;
                        App.BaseWindow.InterPreteMessage(nevent);
                     //   System.Diagnostics.Trace.WriteLine(nevent.MessageCode+"   :    "+nevent.Args.ToString());
                    }
                   
                }

            }
            public static void Stop()
            {
                Run = false;
            }
        }


       
    } 
    // Screen Proparty
        public class Screen
        {
            internal void InitScreen()
            {
                BaseWindow = App.BaseWindow;
                ScreenCanvas = BaseWindow.virtualscreen;
                ScreenCenter = new Vector2((float)ScreenCanvas.ActualWidth / 2, (float)ScreenCanvas.ActualWidth / 2);

            }

            public System.Windows.Controls.Canvas ScreenCanvas { get; set; }
            public MainWindow BaseWindow { set; get; }
            public Vector2 ScreenCenter { set; get; }
            public void SetScreenCenter(float x, float y)
            {
                ScreenCenter = new Vector2((float)ScreenCanvas.ActualWidth / 2, (float)ScreenCanvas.ActualWidth / 2);
                RangeX = 2;
                RangeY = 1;
            }


            public float RangeX { get; set; }
            public float RangeY { get; set; }
        }
       
        
      // Start the Nui Engine to Grabb the feilds
        public class KinectHandGrabber
        {

            #region Postures
            AlgorithmicPostureDetector BasicDetector;
            BothHandsBetweenHeadAndSpineDetector BHBHSDetector;
            UserInstageDectedtor UserInStage;
            InvirtualBoxPostures inbox;
            SholderJointOrantation SkeOr;
            #endregion

            #region Detectors
            public LefthandDistanceInBound lefthanddistance { set; get; }
            public TwoHandDistance twohandDistance { set; get; }
            #endregion


            #region Nui Navigation

            HandMotionDetector NavigationStateEngine=new HandMotionDetector();
           

            #endregion

            private Screen screen;
           
            public Vector2 LefthandLocation{set;get;}
            public Vector2 RighthandLocation{set;get;}
            KinectGestureManager eng;
            public DtwGestureRecognizer GestureRecogniser;
            private ScreencordMapper Screen_mapper;
            public KinectHandGrabber(Screen scr)
            {
                screen = scr;
               
                #region  Postors
                BasicDetector = new AlgorithmicPostureDetector(NavigationStateEngine.GetContext());
                BHBHSDetector = new BothHandsBetweenHeadAndSpineDetector(NavigationStateEngine.GetContext());
                UserInStage = new UserInstageDectedtor(NavigationStateEngine.GetContext());
                inbox = new InvirtualBoxPostures(NavigationStateEngine.GetContext());
                SkeOr = new SholderJointOrantation(NavigationStateEngine.GetContext());


                BasicDetector.PostureDetected += OnPostureDetected;
                BHBHSDetector.PostureDetected += OnPostureDetected;
                UserInStage.PostureDetected += OnPostureDetected;
                inbox.PostureDetected += OnPostureDetected;
                SkeOr.PostureDetected += OnPostureDetected;

              



                #endregion

                #region Detectors
                lefthanddistance = new LefthandDistanceInBound();
                twohandDistance = new TwoHandDistance();
                #endregion

            }

            private void GestureDetectedCallback(string Gesturename)
            {
                
                   // System.Diagnostics.Trace.WriteLine(Gesturename);
                
                   
                    NuiEventManager.PostEvent(new NuiEvent(KinectWindows.Messages.WindowMessages.NUI_MSG_GESTURE_RECOGNISED, new String[] { Gesturename }));
            }

            private void OnPostureDetected(string Posturename)
            {

                Console.WriteLine(Posturename);
                NuiEventManager.PostEvent(new NuiEvent(WindowMessages.NUI_MSG_POSTURE_DETECTED, new String[] { Posturename }));
            }
            internal KinectGestureManager GetNuiEngine()
            {
               
                return eng;
            }
            public KinectGestureManager _Manager { get; set; }
            internal  void StartSensor()
            {
                _Manager = KinectGestureManager.New();
                _Manager.EnableKinect = true;
                _Manager.OnJointFrameReady += JointFrameReady;
                _Manager.OnGestureDetected += GestureDetectedCallback;
                dim = 12;
                threshold = 0.6;
                firstThreshold = 2;
                minLen = 10;
                GestureRecogniser = new DtwGestureRecognizer(dim, threshold, firstThreshold, minLen);

                GestureTools.LoadGesturesFromFile(@"RecordedGestures2011-07-06_22-34.txt", ref GestureRecogniser);
           
            }

         
            protected void JointFrameReady(Vector3 Lefthand, Vector3 RightHand, Vector3 ShoulderLeft, Vector3 ShoulderRight, Vector3 Spine, Vector3 Head, Vector3 Position)
            {
                Update(Lefthand, RightHand, ShoulderLeft, ShoulderRight, Spine, Head, Position);
            }

            public void Update(Vector3 Lefthand, Vector3 RightHand, Vector3 ShoulderLeft, Vector3 ShoulderRight, Vector3 Spine, Vector3 Head, Vector3 Position)
            {

                #region mouse tracking

                Vector2 v1 = Vector2.Zero;
                Vector2 v2 = Vector2.Zero;
                Screen_mapper = new ScreencordMapper(screen.ScreenCanvas);
                Vector3 cog_postion = Vector3.Zero;
                Screen_mapper.SmothingFactor = 1.2;

                //  if (!IsLeftHanded) cog_postion = left_shoulder;
                //  else cog_postion = right_shoulder;
                Vector3 center_shoulder = ShoulderRight - ShoulderLeft;
                cog_postion = center_shoulder;

                Vector2[] Vectors = new Vector2[7];
                #region Mapcord to screen Cord
               Vectors[0]= Screen_mapper.MapKinecktToScreen(cog_postion, Lefthand); 
               Vectors[1]=Screen_mapper.MapKinecktToScreen(cog_postion, RightHand);
               Vectors[2] = Screen_mapper.MapKinecktToScreen(cog_postion, ShoulderLeft);
               Vectors[3] = Screen_mapper.MapKinecktToScreen(cog_postion, ShoulderRight);
               Vectors[4] = Screen_mapper.MapKinecktToScreen(cog_postion, Spine);
               Vectors[5] = Screen_mapper.MapKinecktToScreen(cog_postion, Head);
               Vectors[6] = Screen_mapper.MapKinecktToScreen(cog_postion, Position);
                #endregion
                #region update hand postions on screen
               v2 = _Manager._filterL.FilterJointPostion(Microsoft.Kinect.KinectSensor.KinectSensors[App.ActiveSensor], Vectors[0]);
               v1 = _Manager._filterR.FilterJointPostion(Microsoft.Kinect.KinectSensor.KinectSensors[App.ActiveSensor], Vectors[1]);


                NuiEventManager.PostEvent(new NuiEvent(KinectWindows.Messages.WindowMessages.NUI_MSG_LEFT_HAND_MOVED, new Object[] { v2 }));
                NuiEventManager.PostEvent(new NuiEvent(KinectWindows.Messages.WindowMessages.NUI_MSG_RIGHT_HAND_MOVED, new Object[] { v1 }));
                NuiEventManager.PostEvent(new NuiEvent(KinectWindows.Messages.WindowMessages.NUI_MSG_SKELETON_POS_CHANGED, Vectors));
                #endregion
                #endregion
                #region Detection Cycles and filters
                BasicDetector.TrackPosture(Head, Lefthand, RightHand);
                BHBHSDetector.TrackPosture(Head, Spine, Lefthand, RightHand);
                UserInStage.TrackPosture(Position);
                
                inbox.TrackPosture((ShoulderLeft + ShoulderRight)/2.0f, Lefthand, RightHand);
                SkeOr.TrackPosture(ShoulderRight, ShoulderLeft);
                #endregion
            }


            public int dim { get; set; }

            public double threshold { get; set; }

            public int firstThreshold { get; set; }

            public int minLen { get; set; }
        }
       
        public class SpeechGraber
        {
            String Command { set; get; }
            public SpeechCommander commanders { get; set; }
            public SpeechGraber()
            {
                commanders = new SpeechCommander();
                commanders.OnSpeechRecognised += commanders_OnSpeechRecognised;
                commanders.Run(Microsoft.Kinect.KinectSensor.KinectSensors[App.ActiveSensor]);
            }
            static void commanders_OnSpeechRecognised(object sender, SpeechRecogised e)
            {
               
            }
        }
        
        // The EventEngine     
        public static class NuiEventManager
        {
            private static Queue<NuiEvent> NuiEventBuffer = new Queue<NuiEvent>();
            public static NuiEvent GetEvent()
            {
                if(NuiEventBuffer.Count>0)
                return NuiEventBuffer.Dequeue();
                return null;
            }
            public static void PostEvent(NuiEvent Nuievent)
            {
                NuiEventBuffer.Enqueue(Nuievent);
            }
        }
        // The basic Nui Event Message
        public class NuiEvent
        {
            public WindowMessages MessageCode { set; get; }
            public Object[] Args { set; get; }
            public NuiEvent(WindowMessages code,Object[] args)
            {
                MessageCode = code;
                Args = args;
            }
        }
}
